# Copyright (C) 2006-2008 by Sergio Pistone
# sergio_pistone@yahoo.com.ar
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

$LOAD_PATH << File.expand_path(File.dirname(__FILE__))

require "utils/strings"
require "utils/http"
require "gui/gui"
require "mediawikilyrics"

require "uri"
require "cgi"

class Lyriki < MediaWikiLyrics

	def Lyriki.site_host()
		return "www.lyriki.com"
	end

	def Lyriki.site_name()
		return "Lyriki"
	end

	def Lyriki.control_page()
		return "Lyriki:Wiki-Lyrics"
	end

	def parse_lyrics( response, page_body )

		custom_data = {}

		if (md = /\{\{\s*[Ss]ong\s*\|.*$/m.match( page_body ))

			template_data = parse_template( md[0] )
			template_data["params"].each() do |key, value|
				custom_data[key.to_s()] = value
				if value.is_a?( String )
					value.gsub!( /<br ?\/?>/i, "; " ) if key != "song"
					value.gsub!( /<\/?[^>]+\/?>/, " " )
					value.tr_s!( " \n\r\t", " " )
					value.strip!()
				end
			end

			response.title = custom_data["song"] if custom_data.include?( "song" )

			if custom_data["artist"].is_a?( String )
				response.artist = custom_data["artist"]
			elsif custom_data["artists"].is_a?( Array )
				artist = ""
				custom_data["artists"].each() do |token|
					if token.is_a?( String )
						artist << token.gsub( /\[\[|\]\]/, "" )
					elsif token.is_a?( Hash ) && token["name"].downcase() == "song artist" && token["params"][1]
						artist << token["params"][1]
					end
				end
				artist.gsub!( /\s*<br *\/?>\s*/i, " " )
				response.artist = artist
			elsif custom_data["artists"].is_a?( String ) # this case is DEPRECATED by Lyriki guides
				response.artist = custom_data["artists"].gsub( /\[\[|\]\]/, "" )
			end

			if custom_data["album"].is_a?( String )
				response.album, response.year = custom_data["album"], custom_data["year"]
			elsif custom_data["albums"].is_a?( Array )
				custom_data["albums"].each() do |token|
					if token.is_a?( String )
						if (md = /([^:]+):(.+) \(([0-9]{4,4})\)/.match( token ))
							response.album, response.year = md[2], md[3]
							break
						end
					elsif token.is_a?( Hash )
						if token["name"].downcase() == "song album" && token["params"][2] && token["params"][3]
							response.album, response.year = token["params"][2], token["params"][3]
							break
						end
					end
				end
			end

		end

		custom_data["reviewed"] = (/\{\{[Aa]utoGenerated\}\}/.match( page_body ) == nil)

		if (md = /<lyrics>(.*)<\/lyrics>/im.match( page_body ))
	 		page_body = md[1]
			page_body.gsub!( /[ \t]*[\r\n][ \t]*/m, "\n" )
		else
			page_body.gsub!( /\{\{.*\}\}\n?/, "" )
			page_body.gsub!( /\[\[Category:.*\]\]\n?/, "" )
			page_body.gsub!( /\ *== *(External *Links|Links) *==.*$/im, "" )
			page_body = page_body.split( "\n" ).collect() do |line|
				if line.index( /\s/ ) == 0
					"\n" + line
				else
					line
				end
			end.join( "" )
			page_body.gsub!( /\s*<br ?\/?>\s*/i, "\n" )
		end

		response.lyrics = page_body if ! Strings.empty?( page_body )
		response.custom_data = custom_data

	end

	def Lyriki.build_tracks( album_data )
		ret = ""
		album_data.tracks.each() do |track|
			track_length = track.length > 0 ?
				"|#{track.length / 60}:#{track.length % 60 < 10 ? "0#{track.length % 60}" : track.length % 60}" :
				""
			track_artist = cleanup_title_token( track.artist )
			track_title  = cleanup_title_token( track.title )
			if album_data.various_artists?
				ret += "# {{song link va|#{track_artist}|#{track_title}#{track_length}}}\n"
			else
				ret += "# {{song link|#{track_artist}|#{track_title}#{track_length}}}\n"
			end
		end
		return ret
	end

	def Lyriki.build_album_page( reviewed, artist, album, year, month, day, tracks, album_art )

		raise ArgumentError if Strings.empty?( artist ) || Strings.empty?( album ) || Strings.empty?( tracks )

		s_name = get_sort_name( album )
		s_letter = get_sort_letter( album )

		album_art = nil if ! year || album_art == build_album_art_name( artist, album, year, "jpg", false )

		contents = \
		"#{reviewed ? "" : "{{autoGenerated}}\n"}" \
		"{{Album\n" \
		"| album    = #{album}\n" \
		"| artist   = #{artist}\n" \
		"| released = #{build_date( year, month, day )}\n" \
		"#{album_art ? "| image    = #{album_art}\n" : ""}" \
		"| tracks   =\n"

		return \
		"#{contents}" \
		"#{tracks.strip()}\n" \
		"}}\n" \
		"\n" \
		"{{C:Album|#{s_letter}|#{s_name}}}"
	end

	def Lyriki.build_song_page( reviewed, artist, title, album, year, credits, lyricist, lyrics )

		raise ArgumentError if artist == nil || title == nil

		s_name = get_sort_name( title )
		s_letter = get_sort_letter( title )
		year = year.to_i() <= 1900 ? "" : year.to_s()

		song_page = reviewed ? "": "{{autoGenerated}}\n"

		if (md = /^([^\s].*)\s+feat\.\s+([^\s].*)$/i.match( artist.strip() ))
			artist, fartist = md[1].strip(), md[2]
			song_page <<
			"{{Song\n" \
			"| song     = #{title}\n" \
			"| artists  = {{song artist|#{artist}}}<br />feat. {{song artist|#{fartist}}}\n" \
			"| albums   = {{song album|#{artist}|#{album}|#{year}}}\n" \
			"| credits  = #{credits.to_s().split( "; " ).join( "<br />" )}\n" \
			"| lyricist = #{lyricist.to_s().split( "; " ).join( "<br />" )}\n" \
			"}}\n" \
		else
			song_page <<
			"{{Song\n" \
			"| song     = #{title}\n" \
			"| artist   = #{artist}\n" \
			"| album    = #{album}\n" \
			"| year     = #{year}\n" \
			"| credits  = #{credits.to_s().split( "; " ).join( "<br />" )}\n" \
			"| lyricist = #{lyricist.to_s().split( "; " ).join( "<br />" )}\n" \
			"}}\n" \
		end

		return song_page <<
		"\n" \
		"<lyrics>#{Strings.empty?( lyrics ) ? "<tt>(Instrumental)</tt>" : lyrics}</lyrics>\n" \
		"\n" \
		"{{C:Song|#{s_letter}|#{s_name}}}"
	end

	def Lyriki.build_album_art_name( artist, album, year, extension="jpg", cleanup=true )
		if cleanup
			artist = cleanup_title_token( artist )
			album = cleanup_title_token( album )
		end
		album_art_name = "AlbumArt-#{artist}-#{album}_(#{year})#{Strings.empty?( extension ) ? "" : ".#{extension.strip()}"}".gsub( " ", "_" )
		return Strings.remove_invalid_filename_chars( album_art_name )
	end

	def Lyriki.build_album_art_description( artist, album, year, cleanup=true )
		if cleanup
			artist = cleanup_title_token( artist )
			album = cleanup_title_token( album )
		end
		return "#{artist}:#{album} (#{year})"
	end

	def Lyriki.find_album_art_name( artist, album, year )

		normalized_artist = cleanup_title_token( artist )
		Strings.remove_invalid_filename_chars!( normalized_artist )
		Strings.normalize!( normalized_artist )
		normalized_artist.gsub!( " ", "" )

		normalized_album = cleanup_title_token( album )
		Strings.remove_invalid_filename_chars!( normalized_album )
		Strings.normalize!( normalized_album )
		normalized_album.gsub!( " ", "" )

		year = year.to_s().strip()

		artist = cleanup_title_token( artist )
		Strings.remove_invalid_filename_chars!( artist )
		search_url = "http://#{site_host()}/index.php?ns6=1&search=#{CGI.escape( artist )}&searchx=Search&limit=500"
		response, search_url = HTTP.fetch_page_get( search_url )

		return nil if response == nil || response.body() == nil

		candidates = []
		parse_search_results( response.body(), true ).each() do |result|

			next if result[@@SEARCH_RESULT_TITLE].index( "Image:" ) != 0

			normalized_title = Strings.normalize( result[@@SEARCH_RESULT_TITLE] )
			normalized_title.gsub!( " ", "" )

			matches = 0
			idx1 = normalized_title.index( "albumart" )
			matches += 1 if idx1
			idx1 = idx1 ? idx1 + "albumart".size : 0
			idx2 = normalized_title.index( normalized_artist, idx1 )
			matches += 4 if idx2
			idx2 = idx2 ? idx2 + normalized_artist.size : idx1
			idx3 = normalized_title.index( normalized_album, idx2 )
			next if idx3 == nil
			idx3 = idx3 ? idx3 + normalized_album.size : idx2
			idx3 = normalized_title.index( year, idx3 )
			matches += 2 if idx3

			candidates.insert( -1, [ matches, result[@@SEARCH_RESULT_TITLE] ] )
		end

		if candidates.size > 0
			candidates.sort!() { |x,y| y[0] <=> x[0] }
			return URI.decode( candidates[0][1].slice( "Image:".size..-1 ).gsub( " ", "_" ) )
		else
			return nil
		end
	end

	def Lyriki.cleanup_title_token!( title, downcase=false )
		title.gsub!( /\[[^\]\[]*\]/, "" )
		title.gsub!( /[\[|\]].*$/, "" )
		title.gsub!( /`|´|’/, "'" )
		title.gsub!( /''|«|»/, "\"" )
		title.squeeze!( " " )
		title.strip!()
		title.gsub!( "+", "and" )
		Strings.titlecase!( title, true, downcase )
		return title
	end

end
